using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Pokemon
{
    /// <summary>
    /// This is a game component that implements IUpdateable.
    /// </summary>
    public class Chest : DrawableGameComponent, ITappedInner
    {
        
        #region Attribute

        //private Sprite _mainTexture;

        //private Sprite _effect;

        List<Sprite> _sprites = new List<Sprite>();

        private string _path;

        private bool _isClicked;

        private Vector2 _position;

        private TimeSpan _delayTime;

        private PanelButton _itemPanel;

        private bool _isPanelButtonAdded;

        private GameScreen _owner;

#endregion
     
        /// <summary>
        /// 
        /// </summary>
        /// <param name="game"></param>
        /// <param name="fullPath"></param>
        public Chest(Game game, GameScreen owner, string fullPath, Vector2 position)
            : base(game)
        {
            _path = fullPath;

            _isClicked = false;

            _position = position;

            _owner = owner;

            ShopOpened += ShopOpenProcessing;

            ShopClosed += ShopCloseProcessing;

            ItemBought += ItemBoughtProcessing;

            _isPanelButtonAdded = false;

            Initialize();

            LoadContent();
        }

        public PanelButton ItemPanel
        {
            get { return _itemPanel; }
            set { _itemPanel = value; }
        }

        /// <summary>
        /// Allows the game component to perform any initialization it needs to before starting
        /// to run.  This is where it can query for any required services and load content.
        /// </summary>
        public override void Initialize()
        {
            XDocument doc = XDocument.Load(_path);
            XName name = XName.Get(@"Panel");
            Texture2D texture;
            int numFrame;
            var frameWidth = 0.0f;
            var frameHeight = 0.0f;
            var xCenterPoint = 0.0f;
            var yCenterPoint = 0.0f;
            string panelPath = "";

            if (doc.Document != null)
            {
                var definitions = doc.Document.Descendants(name);
                panelPath = definitions.First().Value;
                ItemPanel = new PanelButton(Game, _owner, panelPath);

                int index = 0;
                name = XName.Get(@"Definition");
                definitions = doc.Document.Descendants(name);
                foreach (var definition in definitions)
                {
                    var xAttribute = definition.Attribute(@"SheetName");
                    if (xAttribute != null)
                    {
                        texture = Game.Content.Load<Texture2D>(xAttribute.Value);
                        
                        xAttribute = definition.Attribute(@"FrameWidth");
                        if (xAttribute != null)
                        {
                            frameWidth = float.Parse(xAttribute.Value);
                            xAttribute = definition.Attribute(@"FrameHeight");
                            if (xAttribute != null)
                            {
                                frameHeight = float.Parse(xAttribute.Value);
                            }
                        }

                        xAttribute = definition.Attribute(@"NumFrame");
                        numFrame = Int32.Parse(xAttribute.Value);

                        xAttribute = definition.Attribute(@"XCenterPoint");

                        xCenterPoint = float.Parse(xAttribute.Value);
                        xAttribute = definition.Attribute(@"YCenterPoint");

                        yCenterPoint = float.Parse(xAttribute.Value);

                        if (index++ == 0)
                            _sprites.Add(new Sprite(texture, numFrame, 
                                new Vector2(frameWidth, frameHeight), new Vector2(xCenterPoint, yCenterPoint), true));
                        else
                            _sprites.Add(new Sprite(texture, numFrame,
                                new Vector2(frameWidth, frameHeight), new Vector2(xCenterPoint, yCenterPoint), false));
                    }
                }
            }            
            base.Initialize();
        }

        /// <summary>
        /// 
        /// </summary>
        protected override void LoadContent()
        {
            for (var i = 0; i < _itemPanel.Grid[0].Rows; i++)
                for (var j = 0; j < _itemPanel.Grid[0].Cols; j++)
                {
                    _itemPanel.Grid[0].Blanks[i, j].Clicked += PushableBlankAdditionFunc;
                }
        }

        /// <summary>
        /// Allows the game component to update itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public override void Update(GameTime gameTime)
        {
            _delayTime += gameTime.ElapsedGameTime;

            if (_delayTime.Milliseconds <= 100)
                return;

            _delayTime = TimeSpan.Zero;

            if (_isClicked)//Neu user da tap vao chest
            {
                _sprites[0].Update(); //Update frame

                if (_sprites[0].FrameIndex == 0) //Neu het 1 chu ky frame
                {
                    Clicked += DoClick; //Thi tro ve trang thai ban dau
                    _isClicked = false; //Tra bien _isClick ve false
                }
            }
            base.Update(gameTime);
        }

        public override void Draw(GameTime gameTime)
        {
            _sprites[0].Draw((SpriteBatch)Game.Services.GetService(typeof(SpriteBatch)), _position, Color.White);
            OnClicked(!_isPanelButtonAdded);
            if (_isPanelButtonAdded)
            {
                ItemPanel.Draw(gameTime);
            }
            base.Draw(gameTime);
        }

        #region Event: Open Chest for user choose item to buy

        public delegate void Click(bool isOpen);

        private event Click Clicked;

        private void OnClicked(bool isOpen)
        {
            Click handler = Clicked;
            if (handler != null) handler(isOpen);
        }

        private void DoClick(bool isOpen)
        {
            LayerManager layer = (LayerManager) Game.Services.GetService(typeof (LayerManager));
            if (isOpen)
            {                
                layer.Add(ItemPanel, 8);
                _isPanelButtonAdded = true;               
            }
            else
            {
                layer.Remove(ItemPanel);
                _isPanelButtonAdded = false;                
            }
            Clicked -= DoClick;
        }

#endregion

        public bool CheckTapped(Point p)
        {
            Rectangle rect = new Rectangle((int)_position.X, (int)_position.Y, (int)_sprites[0].Size.X, (int)_sprites[0].Size.Y);
            var isTapped = rect.Contains(p);
            if (isTapped)
            {
                _isClicked = true;                                
            }
            return isTapped;
        }

        #region Event: Raise when Shop Button Clicked

        private delegate void DelegateShop();

        private event DelegateShop ShopOpened;

        public void OnShopOpened()
        {
            DelegateShop handler = ShopOpened;
            if (handler != null) handler();
        }

        private void ShopOpenProcessing()
        {
            if (!_isPanelButtonAdded)
            {
                LayerManager layer = (LayerManager) Game.Services.GetService(typeof (LayerManager));
                layer.Add(ItemPanel, 8);
                _isPanelButtonAdded = true;
            }                        
        }
        #endregion

        #region Event: Raise when User cancel Shop        

        private event DelegateShop ShopClosed;

        public void OnShopClosed()
        {
            DelegateShop handler = ShopClosed;
            if (handler != null) handler();
        }

        private void ShopCloseProcessing()
        {
            if (_isPanelButtonAdded)
            {
                LayerManager layer = (LayerManager)Game.Services.GetService(typeof(LayerManager));
                layer.Remove(ItemPanel);
                _isPanelButtonAdded = false;
            }            
        }

        #endregion

        #region Event: Raise when User Bought Item

        private delegate void ShopItemBought(Card c);

        private event ShopItemBought ItemBought;

        public void OnItemBought(Card c)
        {
            ShopItemBought handler = ItemBought;
            if (handler != null) handler(c);
        }

        private void ItemBoughtProcessing(Card c)
        {            
            Card card = new Card(Game, @"Content/Textures/Shop/CardDef.xml", ItemPanel.Grid[0], 
                ItemPanel.Grid[0].Blanks[0, 0].Position, ItemPanel.Grid[0].Blanks[0, 0].Size);
            ItemPanel.InsertCard(card);         
        }

        #endregion
        
        public void PushableBlankAdditionFunc(object sender, Point p)
        {
            ShopCloseProcessing();
        }
    }
}
